
package com.be.beadmin.material.impl;

import cn.hutool.core.util.ObjectUtil;
import com.be.beadmin.common.entity.PageEntity;
import com.be.beadmin.common.exception.BeadminException;
import com.be.beadmin.common.utils.JpaQueryBuilder;
import com.be.beadmin.common.utils.JpaQueryBuilderNew;
import com.be.beadmin.common.utils.JpaSortBuilder;
import com.be.beadmin.design.entity.ProductBomOverview;
import com.be.beadmin.design.repository.ProductBomOverviewRepository;
import com.be.beadmin.material.dto.input.PickingTaskDto;
import com.be.beadmin.material.dto.output.PickingDetailsEx;
import com.be.beadmin.material.dto.output.PickingTaskEx;
import com.be.beadmin.material.entity.*;
import com.be.beadmin.material.mapper.PickingDetailsMapperEx;
import com.be.beadmin.material.mapper.PickingTaskMapper;
import com.be.beadmin.material.mapper.PickingTaskMapperEx;
import com.be.beadmin.material.repository.*;
import com.be.beadmin.material.service.PickingTaskService;
import com.be.beadmin.product.entity.WorkOrderInfor;
import com.be.beadmin.product.repository.WorkOrderInforRepository;
import com.be.beadmin.project.entity.BatchPlan;
import com.be.beadmin.project.entity.BatchProduct;
import com.be.beadmin.project.entity.Info;
import com.be.beadmin.project.entity.PlanStage;
import com.be.beadmin.project.repository.BatchPlanRepository;
import com.be.beadmin.project.repository.BatchProductRepository;
import com.be.beadmin.project.repository.InfoRepository;
import com.be.beadmin.project.repository.PlanStageRepository;
import com.be.beadmin.service.util.DateUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
* @description 服务实现
* @author zmy
* @date 2023-05-14
**/
@Service
@RequiredArgsConstructor
public class PickingTaskServiceImpl implements PickingTaskService {

    @Autowired
    private PickingTaskRepository pickingTaskRepository;
    @Autowired
    private PickingTaskMapper pickingTaskMapper;
    @Autowired
    private InfoRepository infoRepository;
    @Autowired
    private BatchProductRepository batchProductRepository;
    @Autowired
    private PickingTaskMapperEx pickingTaskExMapper;

    @Autowired
    private PickingDetailsMapperEx pickingDetailsMapper;
    @Autowired
    private BatchPlanRepository batchPlanRepository;
    @Autowired
    private PickingOverViewRepository pickingOverViewRepository;

    @Autowired
    private PickingReccieveHstRepository pickingReccieveHstRepository;

    @Autowired
    private PickingReccieveDetailsRepository pickingReccieveDetailsRepository;

    @Autowired
    private PickingDetailsRepository pickingDetailsRepository;
    @Autowired
    private PlanStageRepository planStageRepository;

    @Autowired
    private ProductBomOverviewRepository productBomOverviewRepository;

    @Autowired
    private WorkOrderInforRepository workOrderInforRepository;

    @Override
    public Page<PickingTaskEx> getPickingTaskByPage(PageEntity pageEntity) {
            Pageable pageable = PageRequest.of(
            pageEntity.getCurrent() -1,
            pageEntity.getPageSize());
            Page<PickingTask> page = pickingTaskRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
                    List<Predicate> list = new ArrayList<>();
                    Predicate pre1 =   JpaQueryBuilderNew.getPredicate(root, pageEntity.getFilters(), criteriaBuilder);
                    list.add(pre1);
                    Predicate pre2 = criteriaBuilder.equal(root.get(PickingTask_.delete), 0); //过滤为0
                    list.add(pre2);
                    Predicate[] p = new Predicate[list.size()];
                    List<Order> orders = new ArrayList<>();
                    if(pageEntity.getSorters() != null && pageEntity.getSorters().size() > 0) {
                        orders = JpaSortBuilder.getPredicate(root, pageEntity.getSorters(), criteriaBuilder);
                        criteriaQuery.orderBy(orders);
                    } else {
                        criteriaQuery.orderBy(criteriaBuilder.desc(root.get(PickingTask_.createTime).as(Date.class)));
                    }
                    return  criteriaBuilder.and(list.toArray(p));
                    }
                    , pageable);
            Page<PickingTaskEx> page1 = page.map(pickingTaskExMapper::toEntity);
            return page1;

    }


    @Override
    public Page<PickingTaskEx> getPickingTaskByNotReceived(PageEntity pageEntity) {
        Pageable pageable = PageRequest.of(
                pageEntity.getCurrent() -1,
                pageEntity.getPageSize());
        Page<PickingTask> page = pickingTaskRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
                    List<Predicate> list = new ArrayList<>();
                    Predicate pre1 =   JpaQueryBuilder.getPredicate(root, pageEntity.getFilters(), criteriaBuilder);
                    list.add(pre1);
                    Predicate pre2 = criteriaBuilder.equal(root.get(PickingTask_.delete), 0);
                    list.add(pre2);
                    Predicate pre3 = criteriaBuilder.notEqual(root.get(PickingTask_.pickingState), "未分料"); //过滤是未分料的状态
                    Predicate pre4 = criteriaBuilder.notEqual(root.get(PickingTask_.pickingState), "已完成接收");
                    list.add(pre3);
                    list.add(pre4);
                    Predicate[] p = new Predicate[list.size()];
                    List<Order> orders = new ArrayList<>();
                    if(pageEntity.getSorters() != null && pageEntity.getSorters().size() > 0) {
                        orders = JpaSortBuilder.getPredicate(root, pageEntity.getSorters(), criteriaBuilder);
                        criteriaQuery.orderBy(orders);
                    } else {
                        criteriaQuery.orderBy(criteriaBuilder.desc(root.get(PickingTask_.createTime).as(Date.class)));
                    }
                    return  criteriaBuilder.and(list.toArray(p));
                }
                , pageable);
        Page<PickingTaskEx> page1 = page.map(pickingTaskExMapper::toEntity);
        return page1;
    }

    @Override
    public Page<PickingTaskEx> getPickingReceptionPage(PageEntity pageEntity) {
        Pageable pageable = PageRequest.of(
                pageEntity.getCurrent() -1,
                pageEntity.getPageSize());
        Page<PickingTask> page = pickingTaskRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
                    List<Predicate> list = new ArrayList<>();
                    Predicate pre1 =   JpaQueryBuilder.getPredicate(root, pageEntity.getFilters(), criteriaBuilder);
                    list.add(pre1);
                    Predicate pre2 = criteriaBuilder.equal(root.get(PickingTask_.delete), 0);
                    list.add(pre2);
                    Predicate pre3 = criteriaBuilder.equal(root.get(PickingTask_.pickingState), "已完成接收"); //过滤是未分料的状态
                    list.add(pre3);
                    Predicate[] p = new Predicate[list.size()];
                    List<Order> orders = new ArrayList<>();
                    if(pageEntity.getSorters() != null && pageEntity.getSorters().size() > 0) {
                        orders = JpaSortBuilder.getPredicate(root, pageEntity.getSorters(), criteriaBuilder);
                        criteriaQuery.orderBy(orders);
                    } else {
                        criteriaQuery.orderBy(criteriaBuilder.desc(root.get(PickingTask_.createTime).as(Date.class)));
                    }
                    return  criteriaBuilder.and(list.toArray(p));
                }
                , pageable);
        Page<PickingTaskEx> page1 = page.map(pickingTaskExMapper::toEntity);
        return page1;
    }

    @Override
    public Page<PickingTaskEx> getPickingTaskByReceived(PageEntity pageEntity) {
        Pageable pageable = PageRequest.of(
                pageEntity.getCurrent() -1,
                pageEntity.getPageSize());
        Page<PickingTask> page = pickingTaskRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
                    List<Predicate> list = new ArrayList<>();
                    Predicate pre1 =   JpaQueryBuilder.getPredicate(root, pageEntity.getFilters(), criteriaBuilder);
                    list.add(pre1);
                    Predicate pre2 = criteriaBuilder.equal(root.get(PickingTask_.delete), 0);
                    list.add(pre2);
                    Predicate pre3 = criteriaBuilder.equal(root.get(PickingTask_.pickingState), "车间接收"); //过滤不是车间接收的
                    list.add(pre3);
                    Predicate[] p = new Predicate[list.size()];
                    List<Order> orders = new ArrayList<>();
                    if(pageEntity.getSorters() != null && pageEntity.getSorters().size() > 0) {
                        orders = JpaSortBuilder.getPredicate(root, pageEntity.getSorters(), criteriaBuilder);
                        criteriaQuery.orderBy(orders);
                    } else {
                        criteriaQuery.orderBy(criteriaBuilder.desc(root.get(PickingTask_.createTime).as(Date.class)));
                    }
                    return  criteriaBuilder.and(list.toArray(p));
                }
                , pageable);
        Page<PickingTaskEx> page1 = page.map(pickingTaskExMapper::toEntity);
        return page1;
    }

    @Override
    public void addPickingTask(PickingTaskDto pickingTaskDto) {
            PickingTask result = pickingTaskRepository.findPickingTaskByIdAndDelete(pickingTaskDto.getId(), 0);
            if(ObjectUtil.isNotEmpty(result)) {
                throw new BeadminException("PickingTask不存在,请重新查询");
            }
            PickingTask pickingTask = pickingTaskMapper.toEntity(pickingTaskDto);
            pickingTaskRepository.save(pickingTask);
    }

    @Override
    public List<PickingTask> getPickingTaskBySomething(String s, List<PickingTask> pickingTasks) {
        List<PickingTask> newPickTask = new ArrayList<>();
        for (PickingTask p:pickingTasks) {
            System.out.println("==========================="+p);
            List<PickingDetails> pickingDetails = pickingDetailsRepository.findPickingDetailsByPickingTaskCodeAndDelete(p.getPickingTaskCode(), 0);
            for (PickingDetails pd:pickingDetails) {
                if(pd.getMaterialCode().equals(s)||pd.getMaterialSpec().equals(s)){
                    //存在，就扫满
                    //未收数量=已发数量，已接收数量=0
                    pd.setUnclaimedQty(pd.getUnclaimedQty() + pd.getMaterialQty() - pd.getOutboundQty());
//                    pd.setClaimedQty(pd.getClaimedQty());
                    pd.setThistimeQty(pd.getMaterialQty() - pd.getOutboundQty());

                    System.out.println(pd.getMaterialQty() - pd.getOutboundQty());
                    System.out.println("pd.getThistimeQty==================================================================================================");
                    System.out.println(pd.getThistimeQty());
                    pd.setOutboundQty(pd.getMaterialQty());
                    pd.setNotIssuedQty(0);
                    pickingDetailsRepository.save(pd);
                    newPickTask.add(p);
                    break;
                }
            }
        }
        return newPickTask;
    }

    @Override
    public void updatePickingTask(PickingTaskDto pickingTaskDto) {
            PickingTask pickingTask = pickingTaskRepository.findPickingTaskById(pickingTaskDto.getId());
            pickingTask = pickingTaskMapper.toEntity(pickingTaskDto);
            pickingTaskRepository.save(pickingTask);
    }


    @Override
    public void delPickingTask(String id) {
        PickingTask pickingTask = pickingTaskRepository.findPickingTaskById(id);
        pickingTask.setDelete(1);
        pickingTaskRepository.save(pickingTask);
    }

    @Override
    public void delPickingTasks (List<String> ids) { }

    /**
     * 下发分料任务
     *
     * @param workOrderInfor
     */
    @Override
    public void deliverPickingTask(WorkOrderInfor workOrderInfor) {
        BatchProduct batchProduct = batchProductRepository.findBatchProductByProductCodeAndDelete(workOrderInfor.getBatchProductCode(), 0);
        Info info = infoRepository.findInfoByIdAndDelete(batchProduct.getInfoId(), 0);
        BatchPlan batchPlan = batchPlanRepository.findBatchPlanByIdAndDelete(batchProduct.getBatchPlanId(), 0);
        if (batchPlan == null) {
            throw new BeadminException("未找到批次计划");
        }
        PlanStage stage = planStageRepository.findPlanStageByPlanIdAndStageNameAndDelete(batchPlan.getId(), "生产分料", 0);
        PickingOverView pickingOverView = pickingOverViewRepository.findPickingOverViewByProductCodeAndDelete(workOrderInfor.getBatchProductCode(), 0);
        PickingTask pickingTask = new PickingTask();
        pickingTask.setPickingTaskCode(pickingOverView.getPickingNo());
        pickingTask.setProductCode(info.getProjectCode());
        pickingTask.setProjectName(info.getProjectName());
        pickingTask.setBatchPlanCode(batchPlan.getBatchPlanCode());
        pickingTask.setCurrentBatchCode(String.valueOf(batchPlan.getCurrentBatch()));
        pickingTask.setProductCode(batchProduct.getProductCode());
        pickingTask.setWo(workOrderInfor.getWo());
        pickingTask.setWoDesc(workOrderInfor.getWoDesc());
        pickingTask.setPickingState(pickingOverView.getPickingState());
        pickingTask.setProductType(batchProduct.getProductType());
        pickingTask.setProductTypeName(batchProduct.getProductType());
        pickingTask.setBatchPlanId(batchPlan.getId());
//        pickingTask.setErpOrderNo(info.get());

        pickingTask.setProjectCode(workOrderInfor.getProjectCode());
        pickingTask.setBatchDeliveryTime(batchPlan.getBatchDeliveryDate());
        //计划开始结束
        if(stage.getStagePlanStartTime()!=null) {
            pickingTask.setStagePlanStartTime(stage.getStagePlanStartTime());
        }
        if(stage.getStagePlanEndTime()!=null) {
            pickingTask.setStagePlanEndTime(stage.getStagePlanEndTime());
            pickingTask.setPlanFinishTime(stage.getStagePlanEndTime());
        }
        //实际开始
        pickingTask.setStageStartTime(new Date());
        if(stage.getStageStartTime() == null){
            stage.setStageStartTime(pickingTask.getStageStartTime());
        }
        pickingTaskRepository.save(pickingTask);
    }

    //TODO
    @Transactional
    public void pickingFinish(String id){
        //更新pickingTask表
        boolean isFinished = true;
        PickingTask pickingTask = pickingTaskRepository.findPickingTaskByIdAndDelete(id, 0);
        //判断是否所有物料都已分配

        pickingTask.setPickingFinishTime(DateUtil.transDateFormat(new Date()));
        pickingTask.setStageEndTime(DateUtil.transDateFormat(new Date()));


        //更新pickingOverView表
        PickingOverView pickingOverView = pickingOverViewRepository.findPickingOverViewByProductCodeAndAndPickingNoAndDelete(pickingTask.getProductCode(), pickingTask.getPickingTaskCode(), 0);
        pickingOverView.setPickingState("已分料");
        pickingOverView.setPickingFinishTime(DateUtil.transDateFormat(new Date()));
        //添加PickingReccieveHst记录


        //获取pickingDetail
        List<PickingDetails> pickingDetails = pickingDetailsRepository.findPickingDetailsByPickingTaskCodeAndDelete(pickingTask.getPickingTaskCode(), 0);
        for (PickingDetails p: pickingDetails) {
            if(p.getNotIssuedQty()!=0) isFinished=false;
            //更新PickingReccieveHst
            PickingReccieveHst pickingReccieveHst = new PickingReccieveHst();

            pickingReccieveHst.setPickingNo(p.getPickingTaskCode());
            pickingReccieveHst.setMaterialCode(p.getMaterialCode());
            pickingReccieveHst.setErpOrderNo(pickingTask.getErpOrderNo());
            pickingReccieveHst.setProductCode(pickingTask.getProductCode());
            pickingReccieveHst.setProcessCode(p.getProcessCode());
            pickingReccieveHst.setMaterialRecievedQty( String.valueOf(p.getNotIssuedQty()) );
            pickingReccieveHstRepository.save(pickingReccieveHst);
            //更新pickingReccieveDetails表
            PickingReccieveDetails pickingReccieveDetails = pickingReccieveDetailsRepository.findPickingReccieveDetailsByMaterialCodeAndPickingNoAndDelete(p.getMaterialCode(), p.getPickingTaskCode(), 0);
            pickingReccieveDetails.setMaterialRecievedQty(p.getOutboundQty());
            pickingReccieveDetailsRepository.save(pickingReccieveDetails);
        }

        if(Objects.equals(pickingTask.getPickingState(), "车间接收")) {
            boolean flag = false;
            for (PickingDetails p : pickingDetails) {
                if (p.getNotIssuedQty() != 0) {
                    flag = true;
                }
                p.setClaimedQty(p.getOutboundQty());
                p.setUnclaimedQty(0);
                p.setThistimeQty(0);
                p.setCurrentQty(p.getNotIssuedQty());
                pickingDetailsRepository.save(p);
            }
            if (flag) {
                pickingTask.setPickingState("车间接收");
            } else {
                pickingTask.setPickingState("已完成接收");
            }
            pickingTask.setWorkshopFinishTime(DateUtil.transDateFormat(new Date()));
        }
        else if(isFinished==false){
            pickingTask.setPickingState("未领物料");
        }else {
            pickingTask.setPickingState("已分料");

            //生产分料实际结束时间
            PlanStage planStage = planStageRepository.findPlanStageByIdAndDelete(pickingTask.getBatchPlanId(), 0);
            if(planStage!=null) {
                planStage.setStageEndTime(new Date());
            }
        }
        pickingTaskRepository.save(pickingTask);


    }

    @Override
    public void workshopReception(String id) {
        PickingTask pickingTask = pickingTaskRepository.findPickingTaskByIdAndDelete(id, 0);
        if(pickingTask==null)
            throw new RuntimeException("该任务不存在！");
        boolean flag = false;
        //已接收数量置为已发数量，未收数量置为0
        List<PickingDetails> pickingDetails = pickingDetailsRepository.findPickingDetailsByPickingTaskCodeAndDelete(pickingTask.getPickingTaskCode(), 0);

        double totalClaimedQty = 0;
        for (PickingDetails p:pickingDetails) {
            if(p.getNotIssuedQty() != 0){
                flag = true;
            }
            p.setClaimedQty(p.getOutboundQty());
            p.setUnclaimedQty(0);
            p.setThistimeQty(0);
            p.setCurrentQty(p.getNotIssuedQty());

            totalClaimedQty += p.getOutboundQty();
            pickingDetailsRepository.save(p);
        }

        if(flag) {
            pickingTask.setPickingState("车间接收");

            // 工单第一次接收 计算工单的种类/数量齐套率
            List<ProductBomOverview> productAllBom = productBomOverviewRepository.findProductBomOverviewsByProductCodeAndAndDelete(pickingTask.getProductCode(), 0);
            double totalQty = productAllBom.stream().mapToDouble(ProductBomOverview::getMaterialQty).sum();
            double typeCount = pickingDetails.stream().filter(pickingDetails1 -> pickingDetails1.getClaimedQty() != 0).count();

            WorkOrderInfor workOrderInfo = workOrderInforRepository.findWorkOrderInforByWoAndDelete(pickingTask.getWo(), 0);
            workOrderInfo.setNumPercent(BigDecimal.valueOf(totalClaimedQty / totalQty));
            workOrderInfo.setTypePercent(BigDecimal.valueOf(typeCount / productAllBom.size()));

            workOrderInforRepository.save(workOrderInfo);

            // 同步该工单所属批次的种类/数量齐套率

            List<WorkOrderInfor> workOrderList = workOrderInforRepository.findWorkOrderInforByBatchPlanIdAndDelete(pickingTask.getBatchPlanId(), 0);
            double batchNumPercent = workOrderList.stream().mapToDouble(workOrderInfor -> workOrderInfor.getNumPercent().doubleValue()).sum();
            double batchTypePercent = workOrderList.stream().mapToDouble(workOrderInfor -> workOrderInfor.getTypePercent().doubleValue()).sum();

            BatchPlan batchPlan = batchPlanRepository.findBatchPlanByIdAndDelete(pickingTask.getBatchPlanId(), 0);
            batchPlan.setTypePercent(BigDecimal.valueOf(batchTypePercent/ workOrderList.size()));
            batchPlan.setNumPercent(BigDecimal.valueOf(batchNumPercent / workOrderList.size()));
            batchPlanRepository.save(batchPlan);


        }else{
            pickingTask.setPickingState("已完成接收");
        }
        pickingTask.setWorkshopFinishTime(DateUtil.transDateFormat(new Date()));
        pickingTaskRepository.save(pickingTask);

    }

    /**
     * 删除所有分料信息
     *
     * @param id
     */
    @Override
    public void deletePickingTask(String id) {
    }
}